/*
 *    Copyright (c) 2018-2025, lengleng All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution.
 * Neither the name of the pig4cloud.com developer nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 * Author: lengleng (wangiegie@gmail.com)
 */

package cn.ulc.socket.common.aop;

import cn.hutool.log.Log;
import cn.hutool.log.LogFactory;
import cn.ulc.common.constant.PubDataConstant;
import cn.ulc.common.constant.enums.ResultCode;
import cn.ulc.common.exception.PlatformException;
import cn.ulc.common.util.UserUtils;
import cn.ulc.socket.admin.service.staff.StaffServ;
import cn.ulc.socket.weapp.service.CompanyServ;
import cn.ulc.socket.weapp.service.WxUserService;
import cn.ulc.store.entity.Company;
import cn.ulc.store.entity.staff.Staff;
import cn.ulc.store.entity.user.WeixinUser;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.Arrays;

/**
 * @author liuBin
 * @date 2018/9/15
 * Controller 增强
 */

@Aspect
@Configuration
public class ControllerAop {
    private static final Log log = LogFactory.get();

    @Autowired
    StaffServ staffServ;
    @Autowired
    WxUserService wxUserService;
    @Autowired
    CompanyServ companyServ;


    @Around("within(@org.springframework.web.bind.annotation.RestController *) && !@annotation(cn.ulc.common.annotation.IgnoreAuth)")
    public Object functionAccessCheck(final ProceedingJoinPoint pjp) throws Throwable {
        log.info("进入Aspect");
        // 获取登录用户Company
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        Long userId = UserUtils.getUserId(request);
        String role = UserUtils.getRole(request);
//        String token = request.getHeader("token");
        if(PubDataConstant.LOGIN_ADMIN.equals(role)) {
            Staff user = staffServ.findOne(userId);
            if (user == null) throw new PlatformException(ResultCode.NO_LOGIN.getCode(), "登录信息失效，请重新登录!");
            UserUtils.setUser(user);
            Company company = companyServ.findOne(user.getCompanyId());
            UserUtils.setCompany(company);
        }
        else if(PubDataConstant.LOGIN_WX_USER.equals(role)){
            WeixinUser wxUser = wxUserService.findOne(userId);
            if (wxUser == null) throw new PlatformException(ResultCode.NO_LOGIN.getCode(), "登录信息失效，请重新登录!");
            UserUtils.setUser(wxUser);
            Company company = companyServ.findOne(wxUser.getCompanyId());
            UserUtils.setCompany(company);
        }
        //Function访问权限验证
        log.info("走出Aspect");
        //UserUtils.clearAllUserInfo();
        return pjp.proceed();
    }


    @Pointcut("execution(public * cn.ulc.common.util.Result.*(..))")
    public void pointCutR() {
    }

    /**
     * 拦截器具体实现
     *
     * @param pjp 切点 所有返回对象R
     * @return Result  结果包装
     */
    @Around("pointCutR()")
    public Object methodRHandler(ProceedingJoinPoint pjp) throws Throwable {
        return methodHandler(pjp);
    }


//    @Pointcut("execution(public com.baomidou.mybatisplus.plugins.Page *(..))")
//    public void pointCutPage() {
//    }

    /**
     * 拦截器具体实现
     *
     * @param pjp 切点 所有返回对象Page
     * @return Result  结果包装
     */
//    @Around("pointCutPage()")
//    public Object methodPageHandler(ProceedingJoinPoint pjp) throws Throwable {
//        return methodHandler(pjp);
//    }

    private Object methodHandler(ProceedingJoinPoint pjp) throws Throwable {
        long startTime = System.currentTimeMillis();

        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();

//        String username = request.getHeader(SecurityConstants.USER_HEADER);
//        if (StrUtil.isNotBlank(username)) {
//            log.info("Controller AOP get username:{}", username);
//            UserUtils.setUser(username);
//        }

        log.info("URL : " + request.getRequestURL().toString());
        log.info("HTTP_METHOD : " + request.getMethod());
        log.info("IP : " + request.getRemoteAddr());
        log.info("CLASS_METHOD : " + pjp.getSignature().getDeclaringTypeName() + "." + pjp.getSignature().getName());
        log.info("ARGS : " + Arrays.toString(pjp.getArgs()));

        Object result;

        result = pjp.proceed();
        log.info(pjp.getSignature() + "use time:" + (System.currentTimeMillis() - startTime));

//        if (StrUtil.isNotEmpty(username)) {
//            UserUtils.clearAllUserInfo();
//        }

        return result;
    }
}
